package com.cy.cuiyang_admin.chain;


import com.cy.cuiyang_admin.chain.annotation.AttendHandler;
import com.cy.cuiyang_admin.chain.handler.AttendDetectiveHandler;
import com.cy.cuiyang_admin.pojo.AttendRecordDto;
import com.cy.cuiyang_admin.pojo.AttendanceRecord;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author admin
 */
@Component
public class AttendHandlerChain{
    private static final List<AttendDetectiveHandler> HANDLERS = new CopyOnWriteArrayList<>();
    private static final ThreadLocal<AtomicInteger> THREAD_LOCAL = new ThreadLocal<>();
    public void registerHandler(AttendDetectiveHandler handler){
        HANDLERS.add(handler);
        if(HANDLERS.size() > 1){
            HANDLERS.sort((o1, o2) -> {
                AttendHandler handler1 = o1.getClass().getDeclaredAnnotation(AttendHandler.class);
                AttendHandler handler2 = o2.getClass().getDeclaredAnnotation(AttendHandler.class);
                if(handler1.order() == handler2.order()){
                    return 0;
                }
                return handler1.order() > handler2.order() ? 1 : -1;
            });
        }
    }

    public void doHandler(AttendRecordDto attendRecordDto, AttendanceRecord attendance) {
        AtomicInteger step = THREAD_LOCAL.get();
        if (step == null){
            step = new AtomicInteger(-1);
            THREAD_LOCAL.set(step);
        }
        if (step.incrementAndGet() < HANDLERS.size()) {
            try {
                HANDLERS.get(step.get()).handle(this,attendRecordDto,attendance);
            } catch (Exception e) {
                THREAD_LOCAL.remove();
                throw e;
            }
        }else{
            THREAD_LOCAL.remove();
        }
    }
}
